{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "88555961",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "肖申克的救赎\n",
      "\n",
      "                            导演: 弗兰克·德拉邦特 Frank Darabont   主演: 蒂姆·罗宾斯 Tim Robbins /...\n",
      "9.7\n",
      "3072387人评价\n",
      "{'movie_title': ['肖申克的救赎'], 'movie_num': ['9.7'], 'movie_people_num': ['3072387人评价'], 'movie_synopsis': ['\\n                            导演: 弗兰克·德拉邦特 Frank Darabont\\xa0\\xa0\\xa0主演: 蒂姆·罗宾斯 Tim Robbins /...']}\n"
     ]
    },
    {
     "ename": "PermissionError",
     "evalue": "[Errno 13] Permission denied: 'douban.xlsx'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mPermissionError\u001b[0m                           Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[20], line 75\u001b[0m\n\u001b[0;32m     73\u001b[0m     \u001b[38;5;66;03m# 存储数据================================================================================\u001b[39;00m\n\u001b[0;32m     74\u001b[0m     df \u001b[38;5;241m=\u001b[39m pd\u001b[38;5;241m.\u001b[39mDataFrame(result)\n\u001b[1;32m---> 75\u001b[0m     df\u001b[38;5;241m.\u001b[39mto_excel(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdouban.xlsx\u001b[39m\u001b[38;5;124m'\u001b[39m, index\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[0;32m     77\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmain\u001b[39m():\n\u001b[0;32m     78\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m j \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m10\u001b[39m):\n",
      "File \u001b[1;32mD:\\Anaconda3\\Lib\\site-packages\\pandas\\util\\_decorators.py:333\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m    327\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m>\u001b[39m num_allow_args:\n\u001b[0;32m    328\u001b[0m     warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[0;32m    329\u001b[0m         msg\u001b[38;5;241m.\u001b[39mformat(arguments\u001b[38;5;241m=\u001b[39m_format_argument_list(allow_args)),\n\u001b[0;32m    330\u001b[0m         \u001b[38;5;167;01mFutureWarning\u001b[39;00m,\n\u001b[0;32m    331\u001b[0m         stacklevel\u001b[38;5;241m=\u001b[39mfind_stack_level(),\n\u001b[0;32m    332\u001b[0m     )\n\u001b[1;32m--> 333\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
      "File \u001b[1;32mD:\\Anaconda3\\Lib\\site-packages\\pandas\\core\\generic.py:2417\u001b[0m, in \u001b[0;36mNDFrame.to_excel\u001b[1;34m(self, excel_writer, sheet_name, na_rep, float_format, columns, header, index, index_label, startrow, startcol, engine, merge_cells, inf_rep, freeze_panes, storage_options, engine_kwargs)\u001b[0m\n\u001b[0;32m   2404\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpandas\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mio\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mformats\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mexcel\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ExcelFormatter\n\u001b[0;32m   2406\u001b[0m formatter \u001b[38;5;241m=\u001b[39m ExcelFormatter(\n\u001b[0;32m   2407\u001b[0m     df,\n\u001b[0;32m   2408\u001b[0m     na_rep\u001b[38;5;241m=\u001b[39mna_rep,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m   2415\u001b[0m     inf_rep\u001b[38;5;241m=\u001b[39minf_rep,\n\u001b[0;32m   2416\u001b[0m )\n\u001b[1;32m-> 2417\u001b[0m formatter\u001b[38;5;241m.\u001b[39mwrite(\n\u001b[0;32m   2418\u001b[0m     excel_writer,\n\u001b[0;32m   2419\u001b[0m     sheet_name\u001b[38;5;241m=\u001b[39msheet_name,\n\u001b[0;32m   2420\u001b[0m     startrow\u001b[38;5;241m=\u001b[39mstartrow,\n\u001b[0;32m   2421\u001b[0m     startcol\u001b[38;5;241m=\u001b[39mstartcol,\n\u001b[0;32m   2422\u001b[0m     freeze_panes\u001b[38;5;241m=\u001b[39mfreeze_panes,\n\u001b[0;32m   2423\u001b[0m     engine\u001b[38;5;241m=\u001b[39mengine,\n\u001b[0;32m   2424\u001b[0m     storage_options\u001b[38;5;241m=\u001b[39mstorage_options,\n\u001b[0;32m   2425\u001b[0m     engine_kwargs\u001b[38;5;241m=\u001b[39mengine_kwargs,\n\u001b[0;32m   2426\u001b[0m )\n",
      "File \u001b[1;32mD:\\Anaconda3\\Lib\\site-packages\\pandas\\io\\formats\\excel.py:943\u001b[0m, in \u001b[0;36mExcelFormatter.write\u001b[1;34m(self, writer, sheet_name, startrow, startcol, freeze_panes, engine, storage_options, engine_kwargs)\u001b[0m\n\u001b[0;32m    941\u001b[0m     need_save \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[0;32m    942\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m--> 943\u001b[0m     writer \u001b[38;5;241m=\u001b[39m ExcelWriter(\n\u001b[0;32m    944\u001b[0m         writer,\n\u001b[0;32m    945\u001b[0m         engine\u001b[38;5;241m=\u001b[39mengine,\n\u001b[0;32m    946\u001b[0m         storage_options\u001b[38;5;241m=\u001b[39mstorage_options,\n\u001b[0;32m    947\u001b[0m         engine_kwargs\u001b[38;5;241m=\u001b[39mengine_kwargs,\n\u001b[0;32m    948\u001b[0m     )\n\u001b[0;32m    949\u001b[0m     need_save \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m    951\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n",
      "File \u001b[1;32mD:\\Anaconda3\\Lib\\site-packages\\pandas\\io\\excel\\_openpyxl.py:61\u001b[0m, in \u001b[0;36mOpenpyxlWriter.__init__\u001b[1;34m(self, path, engine, date_format, datetime_format, mode, storage_options, if_sheet_exists, engine_kwargs, **kwargs)\u001b[0m\n\u001b[0;32m     57\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mopenpyxl\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mworkbook\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Workbook\n\u001b[0;32m     59\u001b[0m engine_kwargs \u001b[38;5;241m=\u001b[39m combine_kwargs(engine_kwargs, kwargs)\n\u001b[1;32m---> 61\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(\n\u001b[0;32m     62\u001b[0m     path,\n\u001b[0;32m     63\u001b[0m     mode\u001b[38;5;241m=\u001b[39mmode,\n\u001b[0;32m     64\u001b[0m     storage_options\u001b[38;5;241m=\u001b[39mstorage_options,\n\u001b[0;32m     65\u001b[0m     if_sheet_exists\u001b[38;5;241m=\u001b[39mif_sheet_exists,\n\u001b[0;32m     66\u001b[0m     engine_kwargs\u001b[38;5;241m=\u001b[39mengine_kwargs,\n\u001b[0;32m     67\u001b[0m )\n\u001b[0;32m     69\u001b[0m \u001b[38;5;66;03m# ExcelWriter replaced \"a\" by \"r+\" to allow us to first read the excel file from\u001b[39;00m\n\u001b[0;32m     70\u001b[0m \u001b[38;5;66;03m# the file and later write to it\u001b[39;00m\n\u001b[0;32m     71\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mr+\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_mode:  \u001b[38;5;66;03m# Load from existing workbook\u001b[39;00m\n",
      "File \u001b[1;32mD:\\Anaconda3\\Lib\\site-packages\\pandas\\io\\excel\\_base.py:1246\u001b[0m, in \u001b[0;36mExcelWriter.__init__\u001b[1;34m(self, path, engine, date_format, datetime_format, mode, storage_options, if_sheet_exists, engine_kwargs)\u001b[0m\n\u001b[0;32m   1242\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_handles \u001b[38;5;241m=\u001b[39m IOHandles(\n\u001b[0;32m   1243\u001b[0m     cast(IO[\u001b[38;5;28mbytes\u001b[39m], path), compression\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcompression\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28;01mNone\u001b[39;00m}\n\u001b[0;32m   1244\u001b[0m )\n\u001b[0;32m   1245\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(path, ExcelWriter):\n\u001b[1;32m-> 1246\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_handles \u001b[38;5;241m=\u001b[39m get_handle(\n\u001b[0;32m   1247\u001b[0m         path, mode, storage_options\u001b[38;5;241m=\u001b[39mstorage_options, is_text\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[0;32m   1248\u001b[0m     )\n\u001b[0;32m   1249\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_cur_sheet \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m   1251\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m date_format \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "File \u001b[1;32mD:\\Anaconda3\\Lib\\site-packages\\pandas\\io\\common.py:882\u001b[0m, in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m    873\u001b[0m         handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(\n\u001b[0;32m    874\u001b[0m             handle,\n\u001b[0;32m    875\u001b[0m             ioargs\u001b[38;5;241m.\u001b[39mmode,\n\u001b[1;32m   (...)\u001b[0m\n\u001b[0;32m    878\u001b[0m             newline\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m    879\u001b[0m         )\n\u001b[0;32m    880\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m    881\u001b[0m         \u001b[38;5;66;03m# Binary mode\u001b[39;00m\n\u001b[1;32m--> 882\u001b[0m         handle \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mopen\u001b[39m(handle, ioargs\u001b[38;5;241m.\u001b[39mmode)\n\u001b[0;32m    883\u001b[0m     handles\u001b[38;5;241m.\u001b[39mappend(handle)\n\u001b[0;32m    885\u001b[0m \u001b[38;5;66;03m# Convert BytesIO or file objects passed with an encoding\u001b[39;00m\n",
      "\u001b[1;31mPermissionError\u001b[0m: [Errno 13] Permission denied: 'douban.xlsx'"
     ]
    }
   ],
   "source": [
    "from lxml import etree\n",
    "import requests\n",
    "import pandas as pd\n",
    "import chardet\n",
    "\n",
    "# 获取网页的全部内容===================================================================\n",
    "url = 'https://movie.douban.com/top250'\n",
    "headers = {\n",
    "    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',\n",
    "    'Accept-Encoding': 'gzip, deflate'\n",
    "}\n",
    "response = requests.get(url, headers=headers)\n",
    "encoding = chardet.detect(response.content)['encoding']\n",
    "response.html = response.content.decode(encoding)\n",
    "\n",
    "# 对网页进行解析=======================================================================\n",
    "html=etree.HTML(response.html)\n",
    "# 存储电影相关信息的列表\n",
    "movie_title_list=[]\n",
    "movie_synopsis_list=[]\n",
    "movie_num_list=[]\n",
    "movie_people_num_list=[]\n",
    "for i in range(1,25):\n",
    "    # 拼接地址，地址从xpath helper中获取，如果path中有tbody标签，记得删掉\n",
    "    movie_title_path=\"/html[@class='ua-windows ua-webkit']/body/div[@id='wrapper']/div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/ol[@class='grid_view']/li[\"\\\n",
    "                    +str(i)+\"]/div[@class='item']/div[@class='info']/div[@class='hd']/a/span[@class='title'][1]/text()\"\n",
    "    movie_synopsis_path=\"/html[@class='ua-windows ua-webkit']/body/div[@id='wrapper']/div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/ol[@class='grid_view']/li[\"\\\n",
    "                    +str(i)+\"]/div[@class='item']/div[@class='info']/div[@class='bd']/p[1]/text()\"\n",
    "    movie_num_path=\"/html[@class='ua-windows ua-webkit']/body/div[@id='wrapper']/div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/ol[@class='grid_view']/li[\"\\\n",
    "                    +str(i)+\"]/div[@class='item']/div[@class='info']/div[@class='bd']/div[@class='star']/span[@class='rating_num']/text()\"\n",
    "    movie_people_num_path=\"/html[@class='ua-windows ua-webkit']/body/div[@id='wrapper']/div[@id='content']/div[@class='grid-16-8 clearfix']/div[@class='article']/ol[@class='grid_view']/li[\"\\\n",
    "                            +str(i)+\"]/div[@class='item']/div[@class='info']/div[@class='bd']/div[@class='star']/span[4]/text()\"\n",
    "    # 获取电影名称并处理数据===============================================================\n",
    "    movie_title=html.xpath(movie_title_path)\n",
    "    # 获取电影名称字符串\n",
    "    movie_title=str(movie_title[0])\n",
    "#     # 去除电影名称中的空格\n",
    "#     movie_title=\"\".join(movie_title.split())\n",
    "#     # 去除电影名称尾部的/\n",
    "#     movie_title=movie_title[:-1]\n",
    "    print(movie_title)\n",
    "\n",
    "    # 获取电影简介并处理数据===============================================================\n",
    "    movie_synopsis=html.xpath(movie_synopsis_path)\n",
    "    movie_synopsis=movie_synopsis[0]\n",
    "    print(movie_synopsis)\n",
    "\n",
    "    # 获取电影评分并处理数据===============================================================\n",
    "    movie_num=html.xpath(movie_num_path)\n",
    "    movie_num=movie_num[0]\n",
    "    print(movie_num)\n",
    "\n",
    "    # 获取电影评价人数并处理数据===========================================================\n",
    "    movie_people_num=html.xpath(movie_people_num_path)\n",
    "    movie_people_num=movie_people_num[0]\n",
    "    print(movie_people_num)\n",
    "\n",
    "    # 将获取到的数据分别存入对应列表=======================================================\n",
    "    movie_title_list.append(movie_title)\n",
    "    movie_synopsis_list.append(movie_synopsis)\n",
    "    movie_num_list.append(movie_num)\n",
    "    movie_people_num_list.append(movie_people_num)\n",
    "\n",
    "    # 构建对应的字典\n",
    "    result={\n",
    "        \"movie_title\":movie_title_list,\n",
    "        \"movie_num\":movie_num_list,\n",
    "        \"movie_people_num\":movie_people_num_list,\n",
    "        \"movie_synopsis\":movie_synopsis_list\n",
    "    }\n",
    "    print(result)\n",
    "\n",
    "    # 存储数据================================================================================\n",
    "    df = pd.DataFrame(result)\n",
    "    df.to_excel('douban.xlsx', index=False)\n",
    "\n",
    "def main():\n",
    "    for j in range(1,10):\n",
    "        url=\"https://movie.douban.com/top250/top250?start\"+str(25*(j-1))+\"&filter=\"\n",
    "        get_movie_info(url)\n",
    "        \n",
    "if __name__==\"__main__\":\n",
    "    main()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b65596f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 字典转Dataframe\n",
    "df = pd.DataFrame(result)\n",
    "\n",
    "# DataFrame写入Excel\n",
    "df.to_excel('result.xlsx',index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c69e611b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
